﻿#include <iostream>
extern "C" {
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/bprint.h>
#include <libavutil/error.h>
}

#define INPUT_SAMPLERATE 32000
#define INPUT_FORMAT AV_SAMPLE_FMT_S16
#define INPUT_CHANNEL_LAYOUT AV_CH_LAYOUT_MONO

inline char* av_err2str2(int errnum)
{
    char tmp[AV_ERROR_MAX_STRING_SIZE] = { 0 };
    return av_make_error_string(tmp, AV_ERROR_MAX_STRING_SIZE, errnum);
}

int main()
{

    // 初始化FFmpeg库
    av_register_all();
    avfilter_register_all();


    // 打开输入音频文件
    AVFormatContext* fmt_ctx = nullptr;
    if (avformat_open_input(&fmt_ctx, "input.mp3", NULL, NULL) != 0)
    {
        // 错误处理：无法打开文件
        return -1;
    }

    // 寻找音频流
    if (avformat_find_stream_info(fmt_ctx, NULL) < 0)
    {
        // 错误处理：找不到流信息
        avformat_close_input(&fmt_ctx);
        return -1;
    }

    int audio_stream_idx = -1;
    for (unsigned i = 0; i < fmt_ctx->nb_streams; ++i)
    {
        if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
        {
            audio_stream_idx = i;
            break;
        }
    }
    if (audio_stream_idx == -1)
    {
        // 错误处理：找不到音频流
        avformat_close_input(&fmt_ctx);
        return -1;
    }

    // 创建解码器上下文并打开解码器
    AVCodecContext* dec_ctx = avcodec_alloc_context3(NULL);
    avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[audio_stream_idx]->codecpar);
    AVCodec* decoder = avcodec_find_decoder(dec_ctx->codec_id);
    if (!decoder || avcodec_open2(dec_ctx, decoder, NULL) < 0)
    {
        // 错误处理：找不到或无法打开解码器
        avcodec_free_context(&dec_ctx);
        avformat_close_input(&fmt_ctx);
        return -1;
    }

    // 准备滤镜图描述
    AVFilterGraph* filter_graph = avfilter_graph_alloc();

    AVFilterContext* src_ctx = nullptr;

    const AVFilter* abuffer_filter = avfilter_get_by_name("abuffer");
    AVBPrint args;
    av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC);
    av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s",
        1, dec_ctx->sample_rate,
        dec_ctx->sample_rate,
        av_get_sample_fmt_name(dec_ctx->sample_fmt));

    char ch_layout[64] = { 0 };
    av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0, INPUT_CHANNEL_LAYOUT);
    av_bprintf(&args, ":channel_layout=%s",
        ch_layout);
    avfilter_graph_create_filter(&src_ctx, abuffer_filter, "in", args.str, NULL, filter_graph);


    // 添加sink滤镜（buffersink）
    AVFilterContext* sink_ctx = nullptr;
    const AVFilter* buffersink_filter = avfilter_get_by_name("buffersink");
    avfilter_graph_create_filter(&sink_ctx, buffersink_filter, "out", NULL, NULL, filter_graph);

    // 添加showwavespic滤镜
    AVFilterContext* showwavespic_ctx = nullptr;
    const AVFilter* showwavespic_filter = avfilter_get_by_name("showwavespic");
    avfilter_graph_create_filter(&showwavespic_ctx, showwavespic_filter, "showwaves", NULL, NULL, filter_graph);
    av_opt_set(showwavespic_ctx, "size", "640x120", 0); // 设置输出大小

    avfilter_link(src_ctx, 0, showwavespic_ctx, 0);
    avfilter_link(showwavespic_ctx, 0, sink_ctx, 0);

    avfilter_graph_config(filter_graph, NULL);

    // 循环读取、解码音频包，并将解码后的音频帧推送到滤镜图进行处理
    AVPacket packet;
    while (av_read_frame(fmt_ctx, &packet) >= 0 && packet.stream_index == audio_stream_idx)
    {
        AVFrame* decoded_frame = av_frame_alloc();
        avcodec_send_packet(dec_ctx, &packet);
        int got_frame = 0;
        while (avcodec_receive_frame(dec_ctx, decoded_frame) == 0)
        {
            // 将解码后的音频帧送入滤镜图（此处省略了实际送入的具体代码）
            av_buffersrc_add_frame_flags(src_ctx, decoded_frame, 1);

            // 处理完所有帧后，获取最终的图像缓冲区
            AVFrame* output_frame = nullptr;

            int error = av_buffersink_get_frame_flags(sink_ctx, output_frame, 1);
            if (error >= 0)
            {
                std::cout << "av_buffersink_get_frame_flags" << std::endl;
                // 输出帧已准备好，保存为图片
                // 将output_frame转换为RGB格式或其他适合保存为PNG/JPG的格式
                // 省略了转码和保存到文件的步骤
                // ...

            }
            else
            {
                fprintf(stderr, "Cannot link filters: %s\n", av_err2str2(error));               
            }
            av_frame_unref(decoded_frame);
        }
        av_packet_unref(&packet);
    }

    // 清理资源
    //avfilter_inout_free(&outputs);
    //avfilter_inout_free(&inputs);
    avfilter_graph_free(&filter_graph);
    avcodec_free_context(&dec_ctx);
    avformat_close_input(&fmt_ctx);

    return 0;
}

//int main()
//{
//    // 初始化FFmpeg库
//    av_register_all();
//    avfilter_register_all();
//
//    // 打开输入文件获取音频流
//    AVFormatContext* fmt_ctx = NULL;
//    if (avformat_open_input(&fmt_ctx, "input.mp3", NULL, NULL) != 0 ||
//        avformat_find_stream_info(fmt_ctx, NULL) < 0)
//    {
//        // 错误处理：打开或获取流信息失败
//    }
//
//    int audio_stream_idx = -1;
//    for (int i = 0; i < fmt_ctx->nb_streams; i++)
//    {
//        if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
//        {
//            audio_stream_idx = i;
//            break;
//        }
//    }
//    if (audio_stream_idx == -1)
//    {
//        exit(1);
//        // 错误处理：没有找到音频流
//    }
//
//    AVCodecParameters* codecpar = fmt_ctx->streams[audio_stream_idx]->codecpar;
//
//    // 创建解码器上下文
//    AVCodecContext* dec_ctx = avcodec_alloc_context3(NULL);
//    if (avcodec_parameters_to_context(dec_ctx, codecpar) < 0 ||
//        avcodec_open2(dec_ctx, avcodec_find_decoder(codecpar->codec_id), NULL) < 0)
//    {
//        // 错误处理：解码器上下文初始化或打开失败
//        exit(1);
//    }
//
//    // 创建输出图像帧
//    AVFrame* frame = av_frame_alloc();
//    AVFrame* out_frame = av_frame_alloc();
//    out_frame->format = AV_PIX_FMT_RGB24; // 设置为RGB格式以便于显示
//    out_frame->width = 640;
//    out_frame->height = 120;
//
//    // 创建缓冲区sink滤镜
//    AVFilterContext* buffersink_ctx = NULL;
//    char args[512];
//    sprintf(args, "video_size=%dx%d:pix_fmt=rgb24", out_frame->width, out_frame->height);
//    AVFilterInOut* outputs = avfilter_inout_alloc();
//    AVFilterInOut* inputs = avfilter_inout_alloc();
//    outputs->name = av_strdup("out");
//    outputs->filter_ctx = buffersink_ctx;
//    outputs->pad_idx = 0;
//    outputs->next = NULL;
//
//    // 构建滤镜图描述（使用showspectrumpic滤镜）
//    const char* filter_descr = "aevalsrc=0:d=10[sine];[sine]showspectrumpic=s=640x120:split_channels=1[output]";
//    // 注意：实际应用中可能需要调整 `showspectrumpic` 的参数以适应你的需求
//
//    AVFilterGraph* graph = avfilter_graph_alloc();
//    if (avfilter_graph_parse_ptr(graph, filter_descr, &inputs, &outputs, NULL) < 0 ||
//        avfilter_graph_config(graph, NULL) < 0)
//    {
//        // 错误处理：滤镜图解析或配置失败
//        exit(1);
//    }
//
//    //AVFilterContext* buffersrc_ctx = NULL;
//
//    //const AVFilter* abuffer = avfilter_get_by_name("abuffer");
//
//    //avfilter_graph_create_filter(&buffersrc_ctx, abuffer, "in", args.str, NULL, graph);
//
//    //avfilter_link(buffersrc_ctx, 0, buffersink_ctx, 0);
//
//    // 循环读取和处理音频数据
//    while (true)
//    {
//        AVPacket pkt;
//        if (av_read_frame(fmt_ctx, &pkt) < 0)
//        {
//            break; // 到达文件末尾
//        }
//
//        if (pkt.stream_index == audio_stream_idx)
//        {
//            avcodec_send_packet(dec_ctx, &pkt);
//
//            while (avcodec_receive_frame(dec_ctx, frame) == 0)
//            {
//                // 将音频帧送入滤镜链
//                //av_frame_get_buffer(frame, 0);
//
//                if (av_buffersrc_add_frame_flags(buffersrc_ctx, buf_ref, AV_BUFFERSRC_FLAG_KEEP_REF) < 0)
//                {
//                    exit(1);
//                    // 错误处理：链接滤镜或添加帧失败
//                }
//
//                // 从缓冲区sink取出处理后的图像帧
//                int ret = av_buffersink_get_frame(buffersink_ctx, out_frame);
//                if (ret >= 0)
//                {
//                    // 这里 out_frame 包含了频谱图片数据，可以进一步转换格式后保存为图像文件
//                    // 可能需要使用 sws_scale() 进行色彩空间转换，并调用 av_image_write() 写入文件
//                    exit(1);
//                }
//                else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
//                {
//                    // 没有更多帧或者结束
//                    continue;
//                }
//                else
//                {
//                    // 错误处理
//                    exit(1);
//                }
//            }
//            av_packet_unref(&pkt);
//        }
//    }
//
//    // 清理资源
//    avfilter_inout_free(&outputs);
//    avfilter_inout_free(&inputs);
//    avfilter_graph_free(&graph);
//    avcodec_close(dec_ctx);
//    avcodec_free_context(&dec_ctx);
//    avformat_close_input(&fmt_ctx);
//    av_frame_free(&frame);
//    av_frame_free(&out_frame);
//
//}

//int main()
//{
//    const char* input_filename = "input.wav";
//    const char* output_filename = "output.jpg";
//
//    av_register_all();
//    avcodec_register_all();
//    avfilter_register_all();
//
//    AVFormatContext* format_ctx = avformat_alloc_context();
//    if (avformat_open_input(&format_ctx, input_filename, NULL, NULL) != 0)
//    {
//        fprintf(stderr, "Error opening input file\n");
//        return -1;
//    }
//
//    if (avformat_find_stream_info(format_ctx, NULL) < 0)
//    {
//        fprintf(stderr, "Could not find stream information\n");
//        return -1;
//    }
//
//    AVCodec* codec = avcodec_find_decoder(format_ctx->streams[0]->codecpar->codec_id);
//    AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
//    avcodec_parameters_to_context(codec_ctx, format_ctx->streams[0]->codecpar);
//    avcodec_open2(codec_ctx, codec, NULL);
//
//    AVFilterGraph* filter_graph = avfilter_graph_alloc();
//
//    AVFilterContext* buffersrc_ctx = NULL;
//    AVFilterContext* showwavespics_ctx = nullptr;
//    AVFilterContext* buffersink_ctx = NULL;
//
//    const AVFilter* abuffer = avfilter_get_by_name("abuffer");
//    const AVFilter* showwavespic = avfilter_get_by_name("showspectrumpic");
//    const AVFilter* buffersink = avfilter_get_by_name("buffersink");
//
//
//    AVBPrint args;
//    av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC);
//    av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s",
//        1, codec_ctx->sample_rate,
//        codec_ctx->sample_rate,
//        av_get_sample_fmt_name(codec_ctx->sample_fmt));
//
//    char ch_layout[64] = { 0 };
//    av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0, INPUT_CHANNEL_LAYOUT);
//    av_bprintf(&args, ":channel_layout=%s",
//        ch_layout);
//
//    avfilter_graph_create_filter(&buffersrc_ctx, abuffer, "in", args.str, NULL, filter_graph);
//
//    const char* show_filter_desc = "s=640x480:scale=5thrt:legend=0:start=20:stop=16000";
//    avfilter_graph_create_filter(&showwavespics_ctx, showwavespic, "showwavespic", show_filter_desc, nullptr, filter_graph);
//
//    avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", NULL, NULL, filter_graph);
//
//    avfilter_link(buffersrc_ctx, 0, showwavespics_ctx, 0);
//    avfilter_link(showwavespics_ctx, 0, buffersink_ctx, 0);
//
//    avfilter_graph_config(filter_graph, NULL);
//
//    // 打开输出文件
//    FILE* output_file = fopen(output_filename, "wb");
//
//    AVFrame* frame = av_frame_alloc();
//    AVPacket packet;
//    av_init_packet(&packet);
//
//    while (av_read_frame(format_ctx, &packet) >= 0)
//    {
//        if (packet.stream_index == 0)
//        {
//            if (avcodec_send_packet(codec_ctx, &packet) == 0)
//            {
//                while (avcodec_receive_frame(codec_ctx, frame) == 0)
//                {
//                    // 发送音频帧到滤镜图
//                    av_buffersrc_add_frame(buffersrc_ctx, frame);
//
//                    // 获取输出帧
//                    AVFrame* filtered_frame = av_frame_alloc();
//                    int ret = av_buffersink_get_frame(buffersink_ctx, filtered_frame);
//                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
//                    {
//                        av_frame_free(&filtered_frame);
//                        continue;
//                    }
//                    else if (ret < 0)
//                    {
//                        fprintf(stderr, "Error getting frame from filter\n");
//                        break;
//                    }
//
//                    // 将输出帧写入文件
//                    fwrite(filtered_frame->data[0], 1, filtered_frame->linesize[0], output_file);
//
//                    av_frame_free(&filtered_frame);
//                }
//            }
//        }
//        av_packet_unref(&packet);
//    }
//
//    fclose(output_file);
//
//    avformat_close_input(&format_ctx);
//    avcodec_free_context(&codec_ctx);
//    avfilter_free(buffersrc_ctx);
//    //avfilter_free(buffersink_ctx);
//    avfilter_graph_free(&filter_graph);
//    av_frame_free(&frame);
//
//    avformat_network_deinit();
//
//    return 0;
//}
